/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.disc.analysismodel;

import java.text.DecimalFormat;
import java.util.ListIterator;

import br.ufmg.dees.insane.materialMedia.material.Material;
import br.ufmg.dees.insane.model.disc.element.FrameElement;
import br.ufmg.dees.insane.model.disc.element.ParametricElement;
import br.ufmg.dees.insane.model.disc.fem.FemModel;
import br.ufmg.dees.insane.model.disc.node.Node;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;


/**
*A class representing an axisymetric analysis model
*@author Fonseca, Flavio & Brugiolo, Marco & Lucas, Marcelo & Pitangueira Roque.
*@version 1.0
*@since September 2004
*@see model.discrete.element.ParametricElement
*/


public class AxiSymetricAnalysisM extends AnalysisModel
{
	private static final long serialVersionUID = 1L;

	/** Constructs a AxiSymetricAnalysisM analysis model, sets its type to AxiSymetricAnalysisM.*/
	public AxiSymetricAnalysisM()
	{
		this.setDominion(2);
		this.setNdf(2);
		this.setValidEquation(0,true);
		this.setValidEquation(1,true);
		this.setValidEquation(2,false);
		this.setValidEquation(3,false);
		this.setValidEquation(4,false);
		this.setValidEquation(5,false);
		this.setType("AxiSymetricAnalysisM");
	}
	
//********************************************************************************	
	
	/** Mounts the matrix of the material properties for the analysis model type.
	*@param a The matrix of material properties.
	*@return matrix D related to analysis model type 
	*/
	public IMatrix mountDMatrix(double[][] a)
	{
		IMatrix d = new IMatrix(4,4);
		
		double elast = a[0][0];
		double ni = a[2][0];
		double k = ((elast)/((1+ni)*(1-(2*ni))));
		
		d.setElement(0,0, ((1*k)*(1-ni)));
		d.setElement(0,1, (ni*k));
		d.setElement(0,2, (ni*k));
		d.setElement(0,3, 0);
		d.setElement(1,0, (ni*k));
		d.setElement(1,1, ((1*k)*(1-ni)));
		d.setElement(1,2, (ni*k));
		d.setElement(1,3, 0);
		d.setElement(2,0, (ni*k));
		d.setElement(2,1, (ni*k));
		d.setElement(2,2, ((1*k)*(1-ni)));
		d.setElement(2,3, 0);
		d.setElement(3,0, 0);
		d.setElement(3,1, 0);
		d.setElement(3,2, 0);
		d.setElement(3,3, (0.5*(1-(2*ni))));
		
		return d;
	}
	
//********************************************************************************
	
	/** Return the number of active stresses according to this Analysis model type.*/
	public int getNumberOfActiveStress()
	{
		return 4;
	}
	
//********************************************************************************

	/** Return the number of active strains according to this Analysis model type.*/
	public int getNumberOfActiveStrains()
	{
		return 4;
	}
	
//********************************************************************************
	
	/** Return the non zero stresses that perform in one point. 
	*@param a The IVector containing stresses of the point.
	*@param b The Material that will be used to obtain material properties.
	*@return stressVector The IVector according this Axisymetric Analysis Model.
	*/
	public IVector getStressVector(IVector a, Material b)
	{
			return a;
	}
	
//********************************************************************************
	
	/** Return the non zero strains that perform in one point. 
	*@param a The IVector containing strains of the point.
	*@param b The Material that will be used to obtain material properties.
	*@return strainVector The IVector according this Axysimetric Analysis Model.
	*/
	public IVector getStrainVector(IVector a, Material b)
	{
		return a;
	}
	
//********************************************************************************	
		
	/** Return the String representing the non zero stresses of this Axysimetric Analysis Model.
	*@return The string containing the label of non zero stresses of this Axysimetric Analysis Model.
	*/
	public String getStressLabels()
	{
		return ("sigmaXX sigmaYY sigmaZZ tauXY");
	}
	
//********************************************************************************
	
	/** Return the string representing the non zero strains of this Plane Stress Analysis Model.
	*@return The string containing the label of non zero strains of this Plane Stress Analysis Model.
	*/
	public String getStrainLabels()
	{
		return ("epsilonXX epsilonYY epsilonZZ gammaXY");
	}
	
//********************************************************************************
	
	/** Return the integration factor according to analysis model type.
	*This method will be important for this AxiSymetricAnalysisM.
	*@param n The vector containing the shape functions.
	*@param cN The matrix containing the nodal coordinates in cartesian system.
	*@return The integration factor representing the product of 2pi e r. Where r = Ni * ri.
	*/
	public double getStiffnessFactor(IVector n, IMatrix cN)
	{
		IVector r = new IVector(cN.getNumRow());
		r.zero();
		cN.getColumn(0,r);
		r.scale(2*(Math.PI));
		
		return (n.dot(r));
	}
	
//********************************************************************************
	
	/** Returns the type of the Shape adequate to this type of AnalysisModel.
	*@return The type of the Shape adequate to this type of AnalysisModel.
	*/
	public String getDefaultShapeType()
	{
		return null;
	}
	
//********************************************************************************
	
	/** Returns the nodal rotation matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*@param elm The ParametricElement whose nodal rotation matrix is desired.
	*@return The nodal rotation matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IMatrix nodalRotationMatrix(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Returns the local stiffness matrix of the specified ParametricElement, accordingly to this AnalysisModel type.<br>
	*This matrix does not consider the possible liberations at the extremities of the ParametricElement.
	*@param elm The ParametricElement whose local stiffness matrix is desired.
	*@return The local stiffness matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IMatrix localStiffnessMatrix(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Returns the corrected local stiffness matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*This matrix is the same matrix calculated in the localStiffnessMatrix() method, because there is no liberation at extremities in a truss.
	*@param elm The ParametricElement whose corrected local stiffness matrix is desired.
	*@return The corrected local stiffness matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IMatrix localCorrectedStiffnessMatrix(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Returns the transformation matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*@param elm The ParametricElement whose transformation matrix is desired.
	*@return The transformation matrix of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IMatrix transformationMatrix(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Mounts the shape function matrix accordingly to this AnalysisModel type with the values of two IVectors.<br>
	*The first IVector must contain the shape functions values which will be put in the upper part of the matrix.<br>
	*The second IVector must contain the shape functions values which will be put in the lower part of the matrix (related to the derivated shape functions).
	*@param n1 A IVector containing the shape functions values which will be put in the upper part of the matrix.
	*@param n2 A IVector containing the shape functions values which will be put in the upper part of the matrix.
	*@return The shape function matrix accordingly to this AnalysisModel type.
	*/
	public IMatrix mountMatrixN(IVector n1, IVector n2)
	{
		return null;
	}
	
//********************************************************************************
	
	/**Return the matrix with the shape functions ordered according the AnalysisModel.
	*@param n The IVector containing the values of shape functions evalueted in one point.
	*@return matrixN The IMatrix with the shape functions ordered according the AnalysisModel.
	*/
	public IMatrix mountMatrixN(IVector n1)
	{
		IMatrix matrixN = new IMatrix((this.getNdf()),((this.getNdf())*(n1.getSize())));
		matrixN.setZero();
		
		for(int i = 0; i < (n1.getSize()); i++)
		{
			for(int j = 0; j < (this.getNdf()); j++)
			{
				matrixN.setElement( j, ((this.getNdf()*i)+j), (n1.getElement(i)));
			}
		}
			return matrixN;
	}

//********************************************************************************
	
	/** Returns the local equivalent nodal force vector of the specified ParametricElement, accordingly to this AnalysisModel type.
	*This vector does not consider the possible liberations at the extremities of the ParametricElement.
	*@param elm The ParametricElement whose local equivalent nodal force vector is desired.
	*@return The local equivalent nodal force vector of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IVector localEquivalentForceVector(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Returns the corrected local equivalent nodal force vector of the specified ParametricElement, accordingly to this AnalysisModel type.
	*This vector is the same vector calculated in the localEquivalentForceVector() method, because there is no liberation at extremities in a truss.
	*@param elm The ParametricElement whose corrected local equivalent nodal force vector is desired.
	*@return The corrected local equivalent nodal force vector of the specified ParametricElement, accordingly to this AnalysisModel type.
	*/
	public IVector localCorrectedEquivalentForceVector(ParametricElement elm)
	{
		return null;
	}
	
//********************************************************************************
	
	/** Prints in the screen a table with the valid nodal displacements for this AnalysisModel type.
	*@param mod The FemModel which contains the data to be printed.
	*/
	public void printDisplacements(FemModel mod)
	{
		DecimalFormat fmt = new DecimalFormat();
		fmt.applyPattern("0.000E00");
		Node node;
		ListIterator nodes = mod.getNodesList().listIterator();
		System.out.println("NODE DISPLACEMENTS:");
		System.out.println("Node" +"\t\t"+ "Dx" +"\t\t"+ "Dy");
		
		while (nodes.hasNext()) 
		{
			node = (Node) nodes.next();
			System.out.println("Node " + node.getLabel() +"\t"+ fmt.format(node.getDisplacement(0)) +"\t\t"+ fmt.format(node.getDisplacement(1)));
		}
		System.out.println("\t");
	}
	
//********************************************************************************
	
	/** Prints in the screen a table with the valid actions at elements' extremities for this AnalysisModel type.
	*@param mod The FemModel which contains the data to be printed.
	*/
	public void printActionsAtExtremities(FemModel mod)
	{
		System.out.println("\t");
	}
	
//********************************************************************************
	
	/** Prints in the screen a table with the valid support reactions for this AnalysisModel type.
	*@param mod The FemModel which contains the data to be printed.
	*/
	public  void printReactions(FemModel mod)
	{
		System.out.println("\t");
	}
	
//********************************************************************************
	
	/** Returns the B matrix related to this AxiSymetricAnalysisM 
	*@param dl The matrix containing local derivates of shape functions.
	*@param n The vector containing shape functions in natural coordinates.
	*@param cN The matrix containing nodal coordinates in cartesian system.	
	*@return The matrix B 
	*/
	public IMatrix mountBMatrix(IMatrix dl, IVector n, IMatrix cN) 
	{
		int nNos = dl.getNumCol();
		IMatrix invertJacobian;
		IMatrix dG = new IMatrix(2,nNos);
		IMatrix b = new IMatrix(4,(2*nNos));
		IVector aux = new IVector(nNos);
		dG.setZero();
		b.setZero();
		aux.zero();
		
		invertJacobian = this.invertJacobian(this.getJacobian(dl,cN));
		dG.mul(invertJacobian, dl);
		cN.getColumn(0,aux);
		double x = aux.dot(n);
		
		for(int i = 0; i < nNos; i++) 
		{
			b.setElement(0,(2*i),dG.getElement(0,i));
			b.setElement(1,((2*i)+1),dG.getElement(1,i));
			b.setElement(2,(2*i),((n.getElement(i))/x));
			b.setElement(3,(2*i),dG.getElement(1,i));
			b.setElement(3,((2*i)+1),dG.getElement(0,i));
		}
			return(b);
	}
	
//********************************************************************************
	
	/** Return the inverse of jacobian matrix.
	*@param a The jacobian matrix.
	*@return the inverse of jacobian matrix.
	*/
	protected IMatrix invertJacobian(IMatrix a)
	{
		IMatrix b = new IMatrix(2,2);
		b.setZero();
		double detA = (1/(a.determinantLU()));
		b.setElement(0,0,a.getElement(1,1));
		b.setElement(0,1,((-1)*(a.getElement(1,0))));
		b.setElement(1,0,((-1)*(a.getElement(0,1))));
		b.setElement(1,1,a.getElement(0,0));
		
		b.transpose();
		b.setScale((detA));

		return (b);
	}
	
//********************************************************************************	
	
	/** Return the jacobian matrix.
	*@param dl The matrix of local derivates.
	*@param cN The matrix of nodal coordinates.
	*@return dl * cN The jacobian matrix.
	*/
	public IMatrix getJacobian(IMatrix dl, IMatrix cN)
	{
		IMatrix jacobian = new IMatrix(this.getDominion(),this.getDominion());
		jacobian.setZero();
		jacobian.mul(dl, cN);
		
		return(jacobian);
	}
	
	public IMatrix transformationMatrix(FrameElement elm) {
		return null;
	} 
	
//********************************************************************************

}
